/**
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-01-14 17:39:31
 * @Description  : 角色接口控制器
 */
const Mysequelize = require('@/models')
const R = require('@/models/Response')
const { Role, RolePermission, Permission, User } = require('@/models/model')
const { ERROR_USER_CODE } = require('@/constants/errorCode')
const { generatId } = require('@/utils/idUtil')
const { delModel, sortModel } = require('@/utils/controllerCommon')

/**
 * 列表查询角色接口
 * @param {*} ctx
 * @returns
 */
module.exports.listRole = async (ctx) => {
  const { type, isVisible } = ctx.query
  const whereCondition = {}
  if (type !== undefined) {
    whereCondition.type = +type
  }
  if (isVisible !== undefined) {
    whereCondition.isVisible = +isVisible
  }
  const orderCondition = [['sort']]

  const { page, pageSize } = ctx.query
  const start = (page - 1) * pageSize
  const { rows, count } = await Role.findAndCountAll({
    where: whereCondition,
    include: [
      {
        model: Permission,
        attributes: ['id', 'name', 'ename']
      }
    ],
    offset: +start,
    limit: +pageSize,
    order: orderCondition,
    distinct: true
  })

  ctx.body = R.success({
    page,
    pageSize,
    total: count,
    pages: Math.ceil(count / pageSize),
    items: rows
  })
}

/**
 * 列表查询角色接口,只能查询小于当前用户的角色
 * @param {*} ctx
 * @returns
 */
module.exports.listAuthRole = async (ctx) => {
  const { type, isVisible } = ctx.query
  const whereCondition = {}
  if (type !== undefined) {
    whereCondition.type = +type
  }
  if (isVisible !== undefined) {
    whereCondition.isVisible = +isVisible
  }
  const orderCondition = [['sort']]

  const { page, pageSize } = ctx.query
  const start = (page - 1) * pageSize
  let { rows, count } = await Role.findAndCountAll({
    where: whereCondition,
    include: [
      {
        model: Permission,
        attributes: ['id', 'name', 'ename']
      }
    ],
    offset: +start,
    limit: +pageSize,
    order: orderCondition,
    distinct: true
  })

  const user = await User.findByPk(BigInt(ctx.user.id), {
    include: [
      {
        model: Role,
        as: 'role',
        include: [
          {
            model: Permission,
            attributes: ['id', 'name', 'ename']
          }
        ]
      }
    ]
  })

  // 验证某个角色是否小于当前用户的角色

  const userPermissions = user.role.Permissions.map((item) => item.id)

  rows = rows.map((v) => {
    if (+v.type === 1) {
      return v
    }

    const res2 = v.Permissions.some((item) => {
      const res = userPermissions.includes(item.id)
      if (!res) {
        return true
      }
    })

    if (res2) {
      v.isVisible = 0
    }

    return v
  })
  count = rows.length

  ctx.body = R.success({
    page,
    pageSize,
    total: count,
    pages: Math.ceil(count / pageSize),
    items: rows
  })
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 更新角色对应的权限
 * @param {*} permissionIds 权限ID数组
 * @param {*} roleId 角色ID
 * @param {*} userId 用户ID
 * @param {*} t 事务对象
 */
const updateRolePermission = async (permissionIds, roleId, userId, t) => {
  for (let i = 0; i < permissionIds.length; i++) {
    const nextId = generatId()
    await RolePermission.create(
      {
        id: nextId,
        roleId,
        permissionId: permissionIds[i],
        createUser: userId,
        updateUser: userId
      },
      {
        transaction: t
      }
    )
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 创建角色接口
 * @param {*} ctx
 */
module.exports.createRole = async (ctx) => {
  const { name, desc, type, label, isVisible, permissionIds } = ctx.request.body
  const t = await Mysequelize.transaction()
  const nextId = generatId()
  const sort = await Role.max('sort')

  let createObj = {
    id: nextId,
    name,
    type,
    label,
    isVisible,
    system: 0,
    sort: sort + 1,
    createUser: ctx.user.id,
    updateUser: ctx.user.id
  }
  if (desc) {
    createObj.desc = desc
  }
  try {
    // 到这里可以进行角色的添加了,排序字段默认是最大值
    const role = await Role.create(createObj, {
      transaction: t
    })
    // 操作角色对应的权限
    await updateRolePermission(permissionIds, nextId, ctx.user.id, t)
    await t.commit()
    ctx.logs = {
      roldId: role.id
    }
    ctx.body = R.success()
  } catch (error) {
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.ROLE_CREATE_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 更新角色接口
 * @param {*} ctx
 */
module.exports.updateRole = async (ctx) => {
  const t = await Mysequelize.transaction()
  const { roleId, name, desc, label, isVisible, permissionIds } =
    ctx.request.body
  const updateObj = {
    name,
    // type,
    isVisible,
    label
  }
  if (desc) {
    updateObj.desc = desc
  }

  // 如果角色为系统预设，不进行权限的更新
  const aRole = await Role.findByPk(BigInt(roleId))
  if (aRole.system === 1) {
    console.log('a')
    try {
      // 进行角色信息的更新
      await Role.update(updateObj, {
        where: {
          id: BigInt(roleId)
        },
        transaction: t
      })
      await t.commit()
      ctx.body = R.success()
    } catch (e) {
      await t.rollback()
      ctx.body = R.error(ERROR_USER_CODE.ROLE_UPDATE_ERROR)
    }

    return
  }

  console.log('b')
  try {
    // 进行角色信息的更新
    await Role.update(updateObj, {
      where: {
        id: BigInt(roleId)
      },
      transaction: t
    })
    // 将此角色的权限全部删除后，重新设置
    await RolePermission.destroy({
      where: {
        roleId: BigInt(roleId)
      },
      transaction: t
    })

    await updateRolePermission(permissionIds, roleId, ctx.user.id, t)
    await t.commit()
    ctx.body = R.success()
  } catch (e) {
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.ROLE_UPDATE_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 批量删除角色接口
 * @param {*} ctx
 */
module.exports.delRoles = async (ctx) => {
  await delModel(
    Role,
    ERROR_USER_CODE.ROLE_DEL_ERROR,
    'roleIds'
  )(ctx, [{ model: RolePermission, idName: 'roleId' }])
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 角色排序接口
 * @param {*} ctx
 */
module.exports.sortRoles = async (ctx) => {
  // 传递的角色ID顺序即为排序顺序，取出这些ID对应的sort，sort从小到大排序后，依次赋值
  await sortModel(Role, ERROR_USER_CODE.ROLE_SORT_ERROR, 'roleIds')(ctx)
}
